#include "linux/tty.h"
#include "string.h"
#include "linux/gdt.h"

extern void x64_cpu_check();

#define FOUR_LEVEL_HEAD_TABLE_ADDR 0x8000
#define FIRST_PDPT_ADDR 0x9000
#define FIRST_PDT_ADDR 0xa000

static void prepare_4level_page_table()
{
    int * four_level_head_table_addr = (int *)FOUR_LEVEL_HEAD_TABLE_ADDR;
    memset(four_level_head_table_addr, 0, 4096);

    *four_level_head_table_addr = FIRST_PDPT_ADDR | 0x3;
    *(four_level_head_table_addr + 1) = 0;

    int* pdgt_addr = (int*) FIRST_PDPT_ADDR;
    memset(pdgt_addr, 0, 4096);

    *pdgt_addr = FIRST_PDT_ADDR | 0x3;
    *(pdgt_addr + 1) = 0;

    int* pdt_addr = (int *) FIRST_PDT_ADDR;
    memset(pdt_addr, 0, 4096);

    *pdt_addr = 0 | 0x83;
    *(pdt_addr + 1) = 0;

    *(pdt_addr + 2) = 0x200000 | 0x83;
    *(pdt_addr + 3) = 0;

    __asm__ volatile("mov cr3, ebx;"::"b"(four_level_head_table_addr));
}

static void enter_x64()
{
    prepare_4level_page_table();
    // 开启物理地址扩展功能：PAE cr4.pae = 1
    asm volatile("xchg bx, bx; mov eax, cr4; bts eax, 5; mov cr4, eax;");
    // 设置型号专属寄存器IA32_EFER.LME = 1
    asm volatile("mov ecx, 0x0c0000080; rdmsr; bts eax, 8; wrmsr;");

    asm volatile("mov eax, cr0; or eax, 0x80000000; mov cr0, eax;");
    install_x64_descriptor();
    asm volatile("push 0x0018; push 0x100000; retf;");
}

void kernel_main()
{
    console_init();

    // printk("hello");
    x64_cpu_check();
    enter_x64();
    while (1)
    {        
    }
    
}